package oneD.t3dviewer;
/* Strut.java  Generate a strut (tapered at either end) for Java3D

   History:

   01 Jun 2006  Change floats to double except for setting up normals.
   04 Oct 2005  Created from Cylinder.java.

   Comments:

   Strangely, the order the triangle vertices were specified made a
   difference, and I swapped the order of the last two vertices for
   a couple triangles so they got colored on the right side.  No
   change for the normals.  Cylinder normals are used throughout as a
   simplifying approximation.
 */

import javax.media.j3d.*;
import javax.vecmath.*;

public class Strut {
	public final static int TRIANGLES_PER_FACET = 4;
	public final static int VERTEXES_PER_TRIANGLE = 3;
	public final static int VERTEXES_PER_FACET = TRIANGLES_PER_FACET
			* VERTEXES_PER_TRIANGLE;
	public final static int COORDINATES_PER_VERTEX = 3;
	public final static int COORDINATES_PER_FACET = TRIANGLES_PER_FACET
			* VERTEXES_PER_TRIANGLE * COORDINATES_PER_VERTEX;
	private Shape3D shape;

	public Strut(double radius, double length, int facets, double taperProp,
			Appearance a) {
		if (facets < 3)
			facets = 3;
		double inc = 2.0 * Math.PI / facets;

		if (taperProp < .01)
			taperProp = 0.01;
		else if (taperProp > 1.0)
			taperProp = 1.0;

		TriangleArray geometry = new TriangleArray(facets * VERTEXES_PER_FACET,
				TriangleArray.COORDINATES | TriangleArray.NORMALS);
		float data[] = new float[COORDINATES_PER_FACET];
		float ny2 = 0f;
		float nz2 = 1f;
		float y2 = 0f;
		float z2 = (float) radius;
		for (int i = 0; i < facets; i++) {
			float ny1 = ny2;
			float nz1 = nz2;
			ny2 = (float) Math.sin((i + 1) * inc);
			nz2 = (float) Math.cos((i + 1) * inc);
			float y1 = y2;
			float z1 = z2;
			y2 = (float) radius * ny2;
			z2 = (float) radius * nz2;
			float nymid = (float) Math.sin(i * inc + 0.5 * inc);
			float nzmid = (float) Math.cos(i * inc + 0.5 * inc);

			data[0] = 0f;
			data[1] = 0f;
			data[2] = 0f;
			data[3] = (float) (length * taperProp * 0.5);
			data[4] = y1;
			data[5] = z1;
			data[6] = (float) (length * taperProp * 0.5);
			data[7] = y2;
			data[8] = z2;

			data[9] = (float) length;
			data[10] = 0f;
			data[11] = 0f;
			data[12] = (float) (length * (1f - taperProp * 0.5));
			data[13] = y2;
			data[14] = z2;
			data[15] = (float) (length * (1f - taperProp * 0.5));
			data[16] = y1;
			data[17] = z1;

			data[18] = (float) (length * taperProp * 0.5);
			data[19] = y1;
			data[20] = z1;
			data[21] = (float) (length * (1f - taperProp * 0.5));
			data[22] = y2;
			data[23] = z2;
			data[24] = (float) (length * taperProp * 0.5);
			data[25] = y2;
			data[26] = z2;

			data[27] = (float) (length * taperProp * 0.5);
			data[28] = y1;
			data[29] = z1;
			data[30] = (float) (length * (1.0 - taperProp * 0.5));
			data[31] = y1;
			data[32] = z1;
			data[33] = (float) (length * (1.0 - taperProp * 0.5));
			data[34] = y2;
			data[35] = z2;

			geometry.setCoordinates(VERTEXES_PER_FACET * i, data);

			data[0] = 0f;
			data[1] = nymid;
			data[2] = nzmid;
			data[3] = 0f;
			data[4] = ny1;
			data[5] = nz1;
			data[6] = 0f;
			data[7] = ny2;
			data[8] = nz2;

			data[9] = 0f;
			data[10] = nymid;
			data[11] = nzmid;
			data[12] = 0f;
			data[13] = ny2;
			data[14] = nz2;
			data[15] = 0f;
			data[16] = ny1;
			data[17] = nz1;

			data[18] = 0f;
			data[19] = ny1;
			data[20] = nz1;
			data[21] = 0f;
			data[22] = ny2;
			data[23] = nz2;
			data[24] = 0f;
			data[25] = ny2;
			data[26] = nz2;

			data[27] = 0f;
			data[28] = ny1;
			data[29] = nz1;
			data[30] = 0f;
			data[31] = ny1;
			data[32] = nz1;
			data[33] = 0f;
			data[34] = ny2;
			data[35] = nz2;

			geometry.setNormals(VERTEXES_PER_FACET * i, data);
		}

		shape = new Shape3D(geometry, a);
	}

	Shape3D getShape() {
		return shape;
	}
}
